/**
 * LocalContrastFilterControl.java
 * 
 * @date: 2012-02-09
 * @author: Xiaoyu Guo (MUN# 200982155)
 * This file is part of the course project for COMP 6752, 
 * Application of Computer Graphics. All the file is written
 * by myself.
 */
package mun.cs6752.project.filter.localContrast;

import mun.cs6752.project.filter.abstractClasses.AbstractImageFilterControl;
import mun.cs6752.project.filter.interfaces.IImageFilter;
import mun.cs6752.project.filter.interfaces.IImageFilterParameter;
import mun.cs6752.project.filter.interfaces.IImageProvider;
import mun.cs6752.project.filter.localContrast.LocalContrastFilterParameter.LocalContrastMethods;

import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import javax.swing.JLabel;
import java.awt.GridBagConstraints;
import javax.swing.JSpinner;
import java.awt.Insets;

import javax.swing.ButtonGroup;
import javax.swing.SpinnerNumberModel;
import javax.swing.JRadioButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;

/**
 * @author Xiaoyu Guo
 *
 */
public class LocalContrastFilterControl extends AbstractImageFilterControl {
    private static final long serialVersionUID = 5705120055122316431L;
    
    private JRadioButton rdbtnNiblack;
    private JRadioButton rdbtnSauvola;
    private JSpinner spParamK;
    private JSpinner spParamR;
    private JSpinner spGridSize;
    
    private LocalContrastMethods selectedMethod;
    private double k;
    private double r;
    private int gridSize;
    
    private void setSelectedMethod(LocalContrastMethods value){
        switch(value){
        case Niblack:
            rdbtnNiblack.setSelected(true);
            break;
        case Sauvola:
            rdbtnSauvola.setSelected(true);
            break;
        }
        this.selectedMethod = value;
    }
    
    private void setK(double value){
        this.k = value;
        spParamK.setValue(value);
    }
    
    private void setR(double value){
        this.r = value;
        spParamR.setValue(value);
    }
    
    private void setGridSize(int size){
        this.gridSize = size;
        spGridSize.setValue(size);
    }

    /**
     * @param provider
     * @param filter
     */
    public LocalContrastFilterControl(IImageProvider provider, IImageFilter filter) {
        super(provider, filter);
    }
    
    @Override
    protected void initUI(){
        super.initUI();
        
        JPanel pnlControls = new JPanel();
        add(pnlControls, BorderLayout.CENTER);
        GridBagLayout gbl_pnlControls = new GridBagLayout();
        gbl_pnlControls.columnWidths = new int[]{80, 80, 0};
        gbl_pnlControls.rowHeights = new int[]{0, 0, 0, 0, 0, 0};
        gbl_pnlControls.columnWeights = new double[]{0.0, 0.0, Double.MIN_VALUE};
        gbl_pnlControls.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
        pnlControls.setLayout(gbl_pnlControls);
        
        JLabel lblGridSize = new JLabel("Grid Size");
        GridBagConstraints gbc_lblGridSize = new GridBagConstraints();
        gbc_lblGridSize.insets = new Insets(0, 0, 5, 5);
        gbc_lblGridSize.anchor = GridBagConstraints.EAST;
        gbc_lblGridSize.gridx = 0;
        gbc_lblGridSize.gridy = 0;
        pnlControls.add(lblGridSize, gbc_lblGridSize);
        
        spGridSize = new JSpinner();
        spGridSize.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                setGridSize(((SpinnerNumberModel)spGridSize.getModel()).getNumber().intValue());
            }
        });
        spGridSize.setModel(new SpinnerNumberModel(new Integer(72), new Integer(1), null, new Integer(1)));
        GridBagConstraints gbc_spGridSize = new GridBagConstraints();
        gbc_spGridSize.insets = new Insets(0, 0, 5, 0);
        gbc_spGridSize.fill = GridBagConstraints.HORIZONTAL;
        gbc_spGridSize.gridx = 1;
        gbc_spGridSize.gridy = 0;
        pnlControls.add(spGridSize, gbc_spGridSize);
        
        JLabel lblModel = new JLabel("Model");
        GridBagConstraints gbc_lblModel = new GridBagConstraints();
        gbc_lblModel.anchor = GridBagConstraints.EAST;
        gbc_lblModel.insets = new Insets(0, 0, 5, 5);
        gbc_lblModel.gridx = 0;
        gbc_lblModel.gridy = 1;
        pnlControls.add(lblModel, gbc_lblModel);
        
        rdbtnNiblack = new JRadioButton("Niblack");
        rdbtnNiblack.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(rdbtnNiblack.isSelected()){
                    setSelectedMethod(LocalContrastMethods.Niblack);
                    preview();
                }
            }
        });
        GridBagConstraints gbc_rdbtnNiblack = new GridBagConstraints();
        gbc_rdbtnNiblack.fill = GridBagConstraints.HORIZONTAL;
        gbc_rdbtnNiblack.insets = new Insets(0, 0, 5, 0);
        gbc_rdbtnNiblack.gridx = 1;
        gbc_rdbtnNiblack.gridy = 1;
        pnlControls.add(rdbtnNiblack, gbc_rdbtnNiblack);
        
        rdbtnSauvola = new JRadioButton("Sauvola");
        rdbtnSauvola.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(rdbtnSauvola.isSelected()){
                    setSelectedMethod(LocalContrastMethods.Sauvola);
                    preview();
                }
            }
        });
        rdbtnSauvola.setSelected(true);
        GridBagConstraints gbc_rdbtnSauvola = new GridBagConstraints();
        gbc_rdbtnSauvola.insets = new Insets(0, 0, 5, 0);
        gbc_rdbtnSauvola.fill = GridBagConstraints.HORIZONTAL;
        gbc_rdbtnSauvola.gridx = 1;
        gbc_rdbtnSauvola.gridy = 2;
        pnlControls.add(rdbtnSauvola, gbc_rdbtnSauvola);
        
        ButtonGroup modelGroup = new ButtonGroup();
        modelGroup.add(rdbtnNiblack);
        modelGroup.add(rdbtnSauvola);
        
        JLabel lblK = new JLabel("k");
        GridBagConstraints gbc_lblK = new GridBagConstraints();
        gbc_lblK.anchor = GridBagConstraints.EAST;
        gbc_lblK.insets = new Insets(0, 0, 5, 5);
        gbc_lblK.gridx = 0;
        gbc_lblK.gridy = 3;
        pnlControls.add(lblK, gbc_lblK);
        
        spParamK = new JSpinner();
        spParamK.setModel(new SpinnerNumberModel(new Double(0.5), null, null, new Double(0.05)));
        spParamK.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                setK(((SpinnerNumberModel)spParamK.getModel()).getNumber().doubleValue());
            }
        });
        GridBagConstraints gbc_spParamK = new GridBagConstraints();
        gbc_spParamK.insets = new Insets(0, 0, 5, 0);
        gbc_spParamK.fill = GridBagConstraints.HORIZONTAL;
        gbc_spParamK.gridx = 1;
        gbc_spParamK.gridy = 3;
        pnlControls.add(spParamK, gbc_spParamK);
        
        JLabel lblR = new JLabel("r");
        GridBagConstraints gbc_lblR = new GridBagConstraints();
        gbc_lblR.anchor = GridBagConstraints.EAST;
        gbc_lblR.insets = new Insets(0, 0, 0, 5);
        gbc_lblR.gridx = 0;
        gbc_lblR.gridy = 4;
        pnlControls.add(lblR, gbc_lblR);
        
        spParamR = new JSpinner();
        spParamR.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                setR(((SpinnerNumberModel)spParamR.getModel()).getNumber().doubleValue());
            }
        });
        spParamR.setModel(new SpinnerNumberModel(new Integer(128), null, null, new Integer(1)));
        GridBagConstraints gbc_spParamR = new GridBagConstraints();
        gbc_spParamR.fill = GridBagConstraints.HORIZONTAL;
        gbc_spParamR.gridx = 1;
        gbc_spParamR.gridy = 4;
        pnlControls.add(spParamR, gbc_spParamR);
    }
    
    @Override
    protected void initValue(){
        super.initValue();
        LocalContrastFilterParameter defaultValue = new LocalContrastFilterParameter();
        setK(defaultValue.getK());
        setR(defaultValue.getR());
        setGridSize(defaultValue.getMeanSize());
        setSelectedMethod(defaultValue.getSelectedMethod());
    }

    /* (non-Javadoc)
     * @see mun.cs6752.project.filter.interfaces.IImageFilterControl#getParameter()
     */
    @Override
    public IImageFilterParameter getParameter() {
        return new LocalContrastFilterParameter(k, r, gridSize, selectedMethod);
    }

}
